package app.myproject.dao;

//import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.Query;


public abstract class AbstractDAOImpl<T, K> extends DAOSupport implements AbstractDAO<T, K> {
		
	private Class<?> entityClass;

	@SuppressWarnings("unchecked")
	public AbstractDAOImpl(Class<?> entityClass) {
		this.entityClass = entityClass;
	} 
	
	protected Class<T> getEntityClass() {
		return (Class<T>) entityClass;
	}
	
//	@SuppressWarnings("unchecked")
//	protected Class<T> getEntityClass() {
//		if (entityClass == null) {
//			ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
//			entityClass = (Class<T>) type.getActualTypeArguments()[0];
//		}
//		return entityClass;
//	}

	public T create() {
		try {
			open();				
			return pm.newInstance(getEntityClass());
		}
		finally {
			close();
		}	
	}
	
	public T find(K key) {
		try {
			open();	
			if (key != null)	{
				T object = pm.getObjectById(getEntityClass(), key);
				return pm.detachCopy(object);
			}
		}
		finally {
			close();
		}	
		return null;
	}

	public void save(T object) {
		try {
			if (object != null) {
				open();			
				begin();
				pm.makePersistent(object);
				System.out.println("save");
				commit();
			}
		}
		catch(Exception e) {
			e.printStackTrace();			
			rollback();
		}
		finally {
			close();
		}		
	}

	public void update(T object) {
		
		try {
			if (object != null) {
				open();
				if (JDOHelper.isDetached(object)) { 
					begin();
					pm.makePersistent(object);
					System.out.println("update");
					commit();
				}
			}
		}
		catch(Exception e) {
			e.printStackTrace();
			rollback();
		}		
		finally {
			close();
		}				
	}

	public void delete(T object) {
		try {
			if (object != null) { 
				open();
				if (!JDOHelper.isDeleted(object)) {
					begin();					
					pm.deletePersistent(object);
					commit();					
				}
			}
		}
		catch(Exception e) {
			e.printStackTrace();
			rollback();
		}		
		finally {
			close();
		}
	}

	public void deleteById(K key) {
		try {
			if (key != null)	{
				open();
				begin();				
				T object = pm.getObjectById(getEntityClass(), key);
				if (object != null) { 
					if (!JDOHelper.isDeleted(object)) {
						pm.deletePersistent(object);
					}
				}
				commit();				
			}
		}
		catch(Exception e) {
			e.printStackTrace();
			rollback();
		}
		finally {
			close();
		}		
	}
	
	public List<T> list() {
		List<T> results = new ArrayList<T>();
		try {
			open();
			Query q = pm.newQuery(entityClass);	
			q.addExtension("datanucleus.query.flushBeforeExecution","true");
			results = (List<T>) pm.detachCopyAll((List<T>) q.execute());
			q.closeAll();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
			close();
		}
		return results;
	}
	

	public List<T> list(String fieldName, String fieldValue) {
		List<T> results = new ArrayList<T>();
		try {
			String paramName = fieldName + "Param";
			open();
			Query q = pm.newQuery(entityClass, "name=pName");	
			q.setFilter(fieldName + " == " + paramName);
			q.declareParameters("String " + paramName);
			q.addExtension("datanucleus.query.flushBeforeExecution","true");
			results = (List<T>) pm.detachCopyAll((List<T>) q.execute(fieldValue));
			q.closeAll();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
			close();
		}
		return results;
	}

	public void deleteAll() {}

	public int count() { return 0; }

}
